package com.example.hello.authentication;

import com.example.hello.entity.User;
import com.example.hello.manager.UserManager;
import com.example.hello.po.UserPo;
import com.example.hello.service.PermissionService;
import com.example.hello.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Set;


/**
 * <p>
 *
 * </p>
 *
 * @author 12071
 * @date 2022/7/22 16:38
 */
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    UserManager userManager;
    @Autowired
    UserService userService;
    @Autowired
    PermissionService permissionService;
    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //能进入到这里，表示账号已经通过验证了
        String userName = ShiroUtil.getUser().getName();
        // 包含权限信息用户信息
        UserPo user = userManager.getUserInfoByName(userName);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        // 获取角色
        String role = user.getRole();
        simpleAuthorizationInfo.addRole(role);

        // 获取权限
        Set<String> permissions = user.getPermissions();
        simpleAuthorizationInfo.addStringPermissions(permissions);


        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 这里的 token是从 JWTFilter 的 executeLogin 方法传递过来的，已经经过了解密
        String token = (String) authenticationToken.getCredentials();
//        String userName = token.getUsername();
//        String password = new String(token.getPassword());

        String key = ShiroConstant.USER_LOGIN_TOKEN_PREFIX + token;
        String tokenInRedis = null;
        try {
            tokenInRedis = (String) redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
        }

        if(StringUtils.isBlank(tokenInRedis)){
            throw new AuthenticationException("token已过期");
        }

        String userName = JWTUtil.getUsername(token);
        if(StringUtils.isBlank(userName)){
            throw new AuthenticationException("token校验不通过");
        }

        User user = userManager.getUserByName(userName);
        if(user==null){
            throw new AuthenticationException("用户名或密码错误");
        }
        if(!JWTUtil.verify(token, user.getName(), user.getPassword())){
            throw new AuthenticationException("token校验不通过");
        }

        // TODO: 延长缓存

        return new SimpleAuthenticationInfo(user, token, "shiro_realm");
    }
}
